package com.atguigu.yygh.hosp.service.impl;/*
 * @author: XueYouPeng
 * @time: 2023/6/9 15:16
 */

import com.alibaba.fastjson.JSON;
import com.atguigu.exphandler.YyghException;
import com.atguigu.utils.MD5;
import com.atguigu.yygh.feign.DictFeignClient;
import com.atguigu.yygh.hosp.mapper.HospitalSetMapper;
import com.atguigu.yygh.hosp.repository.HospitalRepository;
import com.atguigu.yygh.hosp.service.HospitalService;
import com.atguigu.yygh.model.hosp.BookingRule;
import com.atguigu.yygh.model.hosp.Hospital;
import com.atguigu.yygh.model.hosp.HospitalSet;
import com.atguigu.yygh.vo.hosp.HospitalQueryVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;

@Service
public class HospitalServiceImpl implements HospitalService {
    @Autowired
    HospitalRepository hospitalRepository;

    @Autowired
    HospitalSetMapper hospitalSetMapper;

    @Autowired
    DictFeignClient dictFeignClient;

    /*
     * 公共需求：校验签名
     * 1、医院编号全局唯一，上传医院接口可以重复调用，如果医院编号已经存在，则执行更新操作，否则执行新增操作
     * 2、医院端传递基本信息中，有logoData字段（表示医院端的logo），该字符串中的空格需要替换成“+”
     * 3、上传的医院状态默认值status=1 （1：可用  0：下线）
     * 4、该接口需要判断该医院是否有权限，也就是检查是否已经开通医院设置，如果没有开通，则抛出自定义异常。
     * 5、创建时间和修改时间自动赋值*/
    @Override
    public void saveHospital(Map<String, Object> paramMap) {
        //医院的编号 唯一 非空
        String hoscode = (String) paramMap.get("hoscode");
        //判断医院是否存在 先判断hoscode是否为空
        if (StringUtils.isEmpty(hoscode)){
            throw new YyghException(20001,"医院编号不可为空");
        }
        //hoscode不为空 则根据hoscode查询医院设置
        QueryWrapper<HospitalSet> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("hoscode",hoscode);
        //用到hospitalSetMapper 查询的是mysql
        HospitalSet hospitalSet = hospitalSetMapper.selectOne(queryWrapper);
        //该接口需要判断该医院是否有权限，也就是检查是否已经开通医院设置，如果没有开通，则抛出自定义异常。
        if (hospitalSet == null){
            throw new YyghException(20001,"该医院暂未开通医院设置");
        }

        //签名校验
        //医院端传递签名  已被MD5加密
        String sign = (String) paramMap.get("sign");
        //医院设置中的签名
        String signKey = hospitalSet.getSignKey();
        //判断签名是否正确
        if (!MD5.encrypt(signKey).equals(sign)){
            throw new YyghException(20001,"签名错误");
        }

        //把穿进来的paramMap转换为hospital
        String jsonString = JSON.toJSONString(paramMap);
        Hospital hospital = JSON.parseObject(jsonString, Hospital.class);

        //上传的医院状态默认值status=1 （1：可用  0：下线）
        //处理有logoData字段
        hospital.setStatus(1);
        hospital.setLogoData(hospital.getLogoData().replaceAll(" ","+"));

        //判断该医院是否存在 通过hoscode去mongodb查询一下
        Hospital hospitalFromMongodb = hospitalRepository.findByHoscode(hoscode);

        //判断是新增还是更新
        if (hospitalFromMongodb == null){
            //执行新增
            hospital.setCreateTime(new Date());
            hospital.setUpdateTime(new Date());
            hospitalRepository.save(hospital);
        }else {
            hospital.setCreateTime(hospitalFromMongodb.getCreateTime());
            hospital.setUpdateTime(new Date());
            //执行更新 要有id
            hospital.setId(hospitalFromMongodb.getId());
            hospitalRepository.save(hospital);
        }
    }


    /*
     * 查询
     * @author: XueYouPeng
     * @time: 2023/6/9 19:06
     */
    @Override
    public Hospital show(Map<String, Object> paramMap) {
        String hoscode = (String) paramMap.get("hoscode");
        if(StringUtils.isEmpty(hoscode)){
            throw new YyghException(20001,"医院编号为空");
        }
        Hospital hospital = hospitalRepository.findByHoscode(hoscode);
        return hospital;
    }

    /*
     * 医院分页查询
     * @author: XueYouPeng
     * @time: 2023/6/9 21:07
     */
    @Override
    public Page<Hospital> hospitalList(Integer pageNum, Integer pageSize, HospitalQueryVo hospitalQueryVo) {
        //准备查询条件
        String provinceCode = hospitalQueryVo.getProvinceCode();
        String hosname = hospitalQueryVo.getHosname();
        String cityCode = hospitalQueryVo.getCityCode();
        //首页上的查询条件
        String districtCode = hospitalQueryVo.getDistrictCode();//区
        String hostype = hospitalQueryVo.getHostype();//医院等级
        //准备好的条件封装到hospital里
        Hospital hospital = new Hospital();

        if (!StringUtils.isEmpty(provinceCode)) {
            hospital.setProvinceCode(provinceCode);
        }

        hospital.setHosname(hosname);
        hospital.setCityCode(cityCode);
        hospital.setDistrictCode(districtCode);
        hospital.setHostype(hostype);

        //模糊匹配查询
        ExampleMatcher exampleMatcher = ExampleMatcher.matching()
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)
                .withIgnoreCase(true);//不区分大小写
        Example<Hospital> example = Example.of(hospital, exampleMatcher);

        Pageable pageable = PageRequest.of(pageNum-1,pageSize,Sort.by(Sort.Direction.DESC,"createTime"));

        //分页
        Page<Hospital> hospitalPage = hospitalRepository.findAll(example, pageable);

        //将每一个医院的医院等级名称+完整地址
        hospitalPage.forEach(item->{
            this.packHospital(item);
        });

        return hospitalPage;
    }

    //根据id修改医院的status，实现上线和下线
    @Override
    public void updateStatus(String id, Integer status) {
        Optional<Hospital> byId = hospitalRepository.findById(id);
        Hospital hospital = byId.get();
        if (hospital == null){
            throw new YyghException(20001,"医院不存在");
        }

        //需求：判断是否重复操作
        if (status == hospital.getStatus()){
            throw new YyghException(20001,"医院已处于" + (status ==1 ? "上线" : "下线") + "状态，请勿重复操作");
        }

        hospital.setStatus(status);
        hospital.setUpdateTime(new Date());
        hospitalRepository.save(hospital);
    }

    //查询医院详情
    @Override
    public Map<String, Object> getHospById(String id) {

        Optional<Hospital> byId = hospitalRepository.findById(id);
        Hospital hospital = byId.get();
        //调用私有方法 查询到这个hospital的相关信息
        this.packHospital(hospital);
        //得到BookingRule实体类中的信息 封装起来
        BookingRule bookingRule = hospital.getBookingRule();

        //hospital和bookingRule要封装 所以定义一个HashMap集合
        HashMap<String, Object> map = new HashMap<>();

        map.put("hospital",hospital);
        map.put("bookingRule",bookingRule);

        return map;
    }

    @Override
    public List<Hospital> findByName(String hosname) {
        Hospital hospital = new Hospital();
        hospital.setHosname(hosname);

        ExampleMatcher exampleMatcher = ExampleMatcher.matching()
                .withIgnoreCase(true)
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING);

        Example<Hospital> example = Example.of(hospital, exampleMatcher);

        List<Hospital> list = hospitalRepository.findAll(example);
        return list;
    }

    @Override
    public Hospital getHospByHoscode(String hoscode) {
        Hospital hospital = hospitalRepository.findByHoscode(hoscode);
        this.packHospital(hospital);
        return hospital;
    }

    private void packHospital(Hospital hospital){
        //调用service_cmn 服务，查询医院等级名称，省市区名称
        String provinceName = dictFeignClient.getName(hospital.getProvinceCode());
        String cityName = dictFeignClient.getName(hospital.getCityCode());
        String districtName = dictFeignClient.getName(hospital.getDistrictCode());

        String hostype = dictFeignClient.getName(hospital.getHostype(), "Hostype");

        hospital.getParam().put("fullAddress",provinceName + cityName + districtName);
        hospital.getParam().put("hostypeString",hostype);
    }
}
